home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / slang / sltermin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  22.3 KB  |  866 lines

  1. /* This file contains enough terminfo reading capabilities sufficient for
  2.  * the slang SLtt interface.
  3.  */
  4.  
  5. /* Copyright (c) 1992, 1995 John E. Davis
  6.  * All rights reserved.
  7.  * 
  8.  * You may distribute under the terms of either the GNU General Public
  9.  * License or the Perl Artistic License.
  10.  */
  11.  
  12. #include <config.h>
  13. #include <stdio.h>
  14. #ifndef USE_SETUPTERM
  15. #include "slang.h"
  16. #include "_slang.h"
  17.  
  18. /*
  19.  * The majority of the comments found in the file were taken from the
  20.  * term(4) man page on an SGI.
  21.  */
  22.  
  23. /* Short integers are stored in two 8-bit bytes.  The first byte contains
  24.  * the least significant 8 bits of the value, and the second byte contains
  25.  * the most significant 8 bits.  (Thus, the value represented is
  26.  * 256*second+first.)  The value -1 is represented by 0377,0377, and the
  27.  * value -2 is represented by 0376,0377; other negative values are illegal.
  28.  * The -1 generally means that a capability is missing from this terminal.
  29.  * The -2 means that the capability has been cancelled in the terminfo
  30.  * source and also is to be considered missing.
  31.  */
  32.  
  33. static int make_integer (unsigned char *buf)
  34. {
  35.    register int lo, hi;
  36.    lo = (int) *buf++; hi = (int) *buf;
  37.    if (hi == 0377)
  38.      {
  39.     if (lo == 0377) return -1;
  40.     if (lo == 0376) return -2;
  41.      }
  42.    return lo + 256 * hi;
  43. }
  44.  
  45. /*
  46.  * The compiled file is created from the source file descriptions of the
  47.  * terminals (see the -I option of infocmp) by using the terminfo compiler,
  48.  * tic, and read by the routine setupterm [see curses(3X).]  The file is
  49.  * divided into six parts in the following order:  the header, terminal
  50.  * names, boolean flags, numbers, strings, and string table.
  51.  * 
  52.  * The header section begins the file.  This section contains six short
  53.  * integers in the format described below.  These integers are (1) the magic
  54.  * number (octal 0432); (2) the size, in bytes, of the names section; (3)
  55.  * the number of bytes in the boolean section; (4) the number of short
  56.  * integers in the numbers section; (5) the number of offsets (short
  57.  * integers) in the strings section; (6) the size, in bytes, of the string
  58.  * table.
  59.  */
  60.  
  61. #define MAGIC 0432
  62.  
  63. /* In this structure, all char * fields are malloced EXCEPT if the 
  64.  * structure is SLTERMCAP.  In that case, only terminal_names is malloced
  65.  * and the other fields are pointers into it.
  66.  */
  67. typedef struct
  68. {
  69. #define SLTERMINFO 1
  70. #define SLTERMCAP  2
  71.    unsigned int flags;
  72.  
  73.    int name_section_size;
  74.    char *terminal_names;
  75.    
  76.    int boolean_section_size;
  77.    unsigned char *boolean_flags;
  78.    
  79.    int num_numbers;
  80.    unsigned char *numbers;
  81.    
  82.    int num_string_offsets;
  83.    unsigned char *string_offsets;
  84.    
  85.    int string_table_size;
  86.    char *string_table;
  87.    
  88. } Terminfo_Type;
  89.  
  90. static char *tcap_getstr (char *, Terminfo_Type *);
  91. static int tcap_getnum (char *, Terminfo_Type *);
  92. static int tcap_getflag (char *, Terminfo_Type *);
  93. static int tcap_getent (char *, Terminfo_Type *);
  94.  
  95. static FILE *open_terminfo (char *file, Terminfo_Type *h)
  96. {
  97.    FILE *fp;
  98.    unsigned char buf[12];
  99.    
  100.    fp = fopen (file, "rb");
  101.    if (fp == NULL) return NULL;
  102.    
  103.    if ((12 == fread ((char *) buf, 1, 12, fp) && (MAGIC == make_integer (buf))))
  104.      {
  105.     h->name_section_size = make_integer (buf + 2);
  106.     h->boolean_section_size = make_integer (buf + 4);
  107.     h->num_numbers = make_integer (buf + 6);
  108.     h->num_string_offsets = make_integer (buf + 8);
  109.     h->string_table_size = make_integer (buf + 10);
  110.      }
  111.    else 
  112.      {
  113.     fclose (fp);
  114.     fp = NULL;
  115.      }
  116.    return fp;
  117. }
  118.    
  119. /* 
  120.  * The terminal names section comes next.  It contains the first line of the
  121.  * terminfo description, listing the various names for the terminal,
  122.  * separated by the bar ( | ) character (see term(5)).  The section is
  123.  * terminated with an ASCII NUL character.
  124.  */
  125.  
  126. /* returns pointer to malloced space */
  127. static unsigned char *read_terminfo_section (FILE *fp, int size)
  128. {
  129.    char *s;
  130.    
  131.    if (NULL == (s = (char *) SLMALLOC (size))) return NULL;
  132.    if (size != fread (s, 1, size, fp))
  133.      {
  134.     SLFREE (s);
  135.     return NULL;
  136.      }
  137.    return (unsigned char *) s;
  138. }
  139.  
  140. static char *read_terminal_names (FILE *fp, Terminfo_Type *t)
  141. {
  142.    return t->terminal_names = (char *) read_terminfo_section (fp, t->name_section_size);
  143. }
  144.  
  145. /*
  146.  * The boolean flags have one byte for each flag.  This byte is either 0 or
  147.  * 1 as the flag is present or absent.  The value of 2 means that the flag
  148.  * has been cancelled.  The capabilities are in the same order as the file
  149.  * <term.h>.
  150.  */
  151.  
  152. static unsigned char *read_boolean_flags (FILE *fp, Terminfo_Type *t)
  153. {
  154.    /* Between the boolean section and the number section, a null byte is
  155.     * inserted, if necessary, to ensure that the number section begins on an
  156.     * even byte offset. All short integers are aligned on a short word
  157.     * boundary.
  158.     */
  159.    
  160.    int size = (t->name_section_size + t->boolean_section_size) % 2;
  161.    size += t->boolean_section_size;
  162.    
  163.    return t->boolean_flags = read_terminfo_section (fp, size);
  164. }
  165.  
  166.  
  167.  
  168. /* 
  169.  * The numbers section is similar to the boolean flags section.  Each
  170.  * capability takes up two bytes, and is stored as a short integer.  If the
  171.  * value represented is -1 or -2, the capability is taken to be missing.
  172.  */
  173.  
  174. static unsigned char *read_numbers (FILE *fp, Terminfo_Type *t)
  175. {
  176.    return t->numbers = read_terminfo_section (fp, 2 * t->num_numbers);
  177. }
  178.  
  179.  
  180. /* The strings section is also similar.  Each capability is stored as a
  181.  * short integer, in the format above.  A value of -1 or -2 means the
  182.  * capability is missing.  Otherwise, the value is taken as an offset from
  183.  * the beginning of the string table.  Special characters in ^X or \c
  184.  * notation are stored in their interpreted form, not the printing
  185.  * representation.  Padding information ($<nn>) and parameter information
  186.  * (%x) are stored intact in uninterpreted form.
  187.  */
  188.  
  189. static unsigned char *read_string_offsets (FILE *fp, Terminfo_Type *t)
  190. {
  191.    return t->string_offsets = (unsigned char *) read_terminfo_section (fp, 2 * t->num_string_offsets);
  192. }
  193.  
  194.  
  195. /* The final section is the string table.  It contains all the values of
  196.  * string capabilities referenced in the string section.  Each string is
  197.  * null terminated.
  198.  */
  199.  
  200. static char *read_string_table (FILE *fp, Terminfo_Type *t)
  201. {
  202.    return t->string_table = (char *) read_terminfo_section (fp, t->string_table_size);
  203. }
  204.  
  205.  
  206. /*
  207.  * Compiled terminfo(4) descriptions are placed under the directory
  208.  * /usr/share/lib/terminfo.  In order to avoid a linear search of a huge
  209.  * UNIX system directory, a two-level scheme is used:
  210.  * /usr/share/lib/terminfo/c/name where name is the name of the terminal,
  211.  * and c is the first character of name.  Thus, att4425 can be found in the
  212.  * file /usr/share/lib/terminfo/a/att4425.  Synonyms for the same terminal
  213.  * are implemented by multiple links to the same compiled file.
  214.  */
  215.  
  216. #define MAX_TI_DIRS 4
  217. static char *Terminfo_Dirs [MAX_TI_DIRS] = 
  218. {
  219.    NULL,
  220.    "/usr/lib/terminfo",
  221.    "/usr/share/lib/terminfo",
  222.    "/usr/local/lib/terminfo"
  223. };
  224.  
  225. char *SLtt_tigetent (char *term)
  226. {
  227.    char *tidir; 
  228.    int i;
  229.    FILE *fp = NULL;
  230.    char file[256];
  231.    Terminfo_Type *ti;
  232.  
  233.    if (term == NULL) return NULL;
  234.    
  235.    if (NULL == (ti = (Terminfo_Type *) SLMALLOC (sizeof (Terminfo_Type))))
  236.      {
  237.     return NULL;
  238.      }
  239.    
  240.    /* If we are on a termcap based system, use termcap */
  241.    if (0 == tcap_getent (term, ti)) return (char *) ti;
  242.        
  243.    Terminfo_Dirs[0] = getenv ("TERMINFO");
  244.    i = 0;
  245.    while (i < MAX_TI_DIRS)
  246.      {
  247.     tidir = Terminfo_Dirs[i];
  248.     if (tidir != NULL)
  249.       {
  250.          sprintf (file, "%s/%c/%s", tidir, *term, term);
  251.          if (NULL != (fp = open_terminfo (file, ti))) break;
  252.       }
  253.     i++;
  254.      }
  255.    
  256.    if (fp != NULL) 
  257.      {
  258.     if (NULL != read_terminal_names (fp, ti))
  259.       {
  260.          if (NULL != read_boolean_flags (fp, ti))
  261.            {
  262.           if (NULL != read_numbers (fp, ti))
  263.             {
  264.                if (NULL != read_string_offsets (fp, ti))
  265.              {
  266.                 if (NULL != read_string_table (fp, ti))
  267.                   {
  268.                  /* success */
  269.                  fclose (fp);
  270.                  ti->flags = SLTERMINFO;
  271.                  return (char *) ti;
  272.                   }
  273.                 SLFREE (ti->string_offsets);
  274.              }
  275.                SLFREE (ti->numbers);
  276.             }
  277.           SLFREE (ti->boolean_flags);
  278.            }
  279.          SLFREE (ti->terminal_names);
  280.       }
  281.     fclose (fp);
  282.      }
  283.    
  284.    SLFREE (ti);
  285.    return NULL;
  286. }
  287.  
  288. typedef struct 
  289. {
  290.    char *name;
  291.    int offset;
  292. }
  293. Tgetstr_Map_Type;
  294.    
  295. Tgetstr_Map_Type Tgetstr_Map [] =
  296. {
  297.    {"@7", 164},                   /* KEY End */
  298.    {"AL", 110},                   /* parm_insert_line */
  299.    {"DL", 106},                   /* parm_delete_line */
  300.    {"RI", 112},                   /* parm_right_cursor */
  301.    {"ac", 146},                   /* acs_chars */
  302.    {"ae", 38},                   /* exit_alt_charset_mode */
  303.    {"as", 25},                   /* enter_alt_charset_mode */
  304.    {"ce", 6},                   /* clr_eol */
  305.    {"cl", 5},                   /* clear_screen */
  306.    {"cm", 10},                   /* cursor_address */
  307.    {"cs", 3},                   /* change_scroll_region */
  308.    {"dc", 21},                   /* delete_character */
  309.    {"ei", 42},                   /* exit_insert_mode */
  310.    {"eA", 155},                   /* enable alt char set */
  311.    {"im", 31},                   /* enter_insert_mode */
  312.    {"k0", 65},                   /* key_f0 */
  313.    {"k1", 66},                   /* key_f1 */
  314.    {"k2", 68},                   /* key_f2 */
  315.    {"k3", 69},                   /* key_f3 */
  316.    {"k4", 70},                   /* key_f4 */
  317.    {"k5", 71},                   /* key_f5 */
  318.    {"k6", 72},                   /* key_f6 */
  319.    {"k7", 73},                   /* key_f7 */
  320.    {"k8", 74},                   /* key_f8 */
  321.    {"k9", 75},                   /* key_f9 */
  322.    {"kA", 78},                   /* key_il */
  323.    {"kC", 57},                   /* key_clear */
  324.    {"kD", 59},                   /* key_dc */
  325.    {"kE", 63},                   /* key_eol, */
  326.    {"kF", 84},                   /* key_sf */
  327.    {"kH", 80},                   /* key_ll */
  328.    {"kI", 77},                   /* key_ic */
  329.    {"kL", 60},                   /* key_dl */
  330.    {"kM", 62},                   /* key_eic, */
  331.    {"kN", 81},                   /* key_npage */
  332.    {"kP", 82},                   /* key_ppage */
  333.    {"kR", 85},                   /* key_sr */
  334.    {"kS", 64},                   /* key_eos, */
  335.    {"kT", 86},                   /* key_stab */
  336.    {"ka", 56},                   /* key_catab */
  337.    {"k;", 67},                   /* key_f10 */
  338.    {"kb", 55},                   /* key_backspace */
  339.    {"kd", 61},                   /* key_down */
  340.    {"kh", 76},                   /* key_home */
  341.    {"kl", 79},                   /* key_left */
  342.    {"kr", 83},                   /* key_right */
  343.    {"kt", 58},                   /* key_ctab */
  344.    {"ku", 87},                   /* key_up */
  345.    {"mb", 26},                   /* enter_blink_mode */
  346.    {"md", 27},                   /* enter_bold_mode */
  347.    {"me", 39},                   /* exit_attribute_mode */
  348.    {"mr", 34},                   /* enter_reverse_mode */
  349.    {"se", 43},                   /* exit_standout_mode */
  350.    {"so", 35},                   /* enter_standout_mode */
  351.    {"sr", 130},                   /* scroll_reverse */
  352.    {"te", 40},                   /* end cursor addressing */
  353.    {"ti", 28},                   /* begin cursor addressing */
  354.    {"up", 19},                   /* cursor_up */
  355.    {"us", 36},                   /* enter_underline_mode */
  356.    {"vb", 45},                   /* flash_screen */
  357.    {"vi", 13},                   /* make cursor invisible */
  358.    {"vs", 20},                   /* make cursor visible */
  359.    {"ke", 88},                   /* out of keypad transmit mode */
  360.    {"ks", 89},                   /* keypad transmit mode */
  361.    {"F1", 216},                   /* key_f11 */
  362.    {"F2", 217},                   /* key_f12 */
  363.    {"F3", 218},                   /* key_f13 */
  364.    {"F4", 219},                   /* key_f14 */
  365.    {"F5", 220},                   /* key_f15 */
  366.    {"F6", 221},                   /* key_f16 */
  367.    {"F7", 222},                   /* key_f17 */
  368.    {"F8", 223},                   /* key_f18 */
  369.    {"F9", 224},                   /* key_f19 */
  370.    {"FA", 225},                   /* key_f20 */
  371.    {"op", 297},                        /* original pair */
  372.    {NULL, 0}
  373. };
  374.  
  375. static int compute_cap_offset (char *cap, Terminfo_Type *t, Tgetstr_Map_Type *map, int max_ofs)
  376. {
  377.    char cha, chb;
  378.    
  379.    cha = *cap++; chb = *cap;
  380.    
  381.    while (map->name != NULL)
  382.      {
  383.     if ((cha == *map->name) && (chb == *(map->name + 1)))
  384.       {
  385.          if (map->offset >= max_ofs) return -1;
  386.          return map->offset;
  387.       }
  388.     map++;
  389.      }
  390.    return -1;
  391. }
  392.  
  393.    
  394. char *SLtt_tigetstr (char *cap, char **pp)
  395. {
  396.    int offset;
  397.    Terminfo_Type *t;
  398.    
  399.    if ((pp == NULL) || (NULL == (t = (Terminfo_Type *) *pp))) return NULL;
  400.    
  401.    if (t->flags == SLTERMCAP) return tcap_getstr (cap, t);
  402.    
  403.    offset = compute_cap_offset (cap, t, Tgetstr_Map, t->num_string_offsets);
  404.    if (offset < 0) return NULL;
  405.    offset = make_integer (t->string_offsets + 2 * offset);
  406.    if (offset < 0) return NULL;
  407.    return t->string_table + offset;
  408. }
  409.  
  410. Tgetstr_Map_Type Tgetnum_Map[] =
  411. {
  412.    {"co", 0},                   /* columns */
  413.    {"li", 2},                   /* lines */
  414.    {NULL, -1}
  415. };
  416.  
  417. int SLtt_tigetnum (char *cap, char **pp)
  418. {
  419.    int offset;
  420.    Terminfo_Type *t;
  421.    
  422.    if ((pp == NULL) || (NULL == (t = (Terminfo_Type *) *pp))) return -1;
  423.  
  424.    if (t->flags == SLTERMCAP) return tcap_getnum (cap, t);
  425.  
  426.    offset = compute_cap_offset (cap, t, Tgetnum_Map, t->num_numbers);
  427.    if (offset < 0) return -1;
  428.    return make_integer (t->numbers + 2 * offset);
  429. }
  430.  
  431. Tgetstr_Map_Type Tgetflag_Map[] =
  432. {
  433.    {"am", 1},                   /* auto_right_margin */
  434.    {"ms", 14},                   /* move_standout_mode */
  435.    {"xs", 3},                   /* ceol_standout_glitch */
  436.    {"sg", 4},                   /* magic cookie glitch */
  437.    {NULL, -1}
  438. };
  439.  
  440. int SLtt_tigetflag (char *cap, char **pp)
  441. {
  442.    int offset;
  443.    Terminfo_Type *t;
  444.    
  445.    if ((pp == NULL) || (NULL == (t = (Terminfo_Type *) *pp))) return -1;
  446.  
  447.    if (t->flags == SLTERMCAP) return tcap_getflag (cap, t);
  448.    
  449.    offset = compute_cap_offset (cap, t, Tgetflag_Map, t->boolean_section_size);
  450.    
  451.    if (offset < 0) return -1;
  452.    return (int) *(t->boolean_flags + offset);
  453. }
  454.  
  455.  
  456.  
  457. /* These are my termcap routines.  They only work with the TERMCAP environment
  458.  * variable.  This variable must contain the termcap entry and NOT the file.
  459.  */
  460.  
  461. static int tcap_getflag (char *cap, Terminfo_Type *t)
  462. {
  463.    char a, b;
  464.    char *f = (char *) t->boolean_flags;
  465.    char *fmax;
  466.    
  467.    if (f == NULL) return 0;
  468.    fmax = f + t->boolean_section_size;
  469.  
  470.    a = *cap;
  471.    b = *(cap + 1);
  472.    while (f < fmax)
  473.      {
  474.     if ((a == f[0]) && (b == f[1]))
  475.       return 1;
  476.     f += 2;
  477.      }
  478.    return 0;
  479. }
  480.  
  481. static char *tcap_get_cap (unsigned char *cap, unsigned char *caps, int len)
  482. {
  483.    unsigned char c0, c1;
  484.    unsigned char *caps_max;
  485.    
  486.    c0 = cap[0];
  487.    c1 = cap[1];
  488.    
  489.    if (caps == NULL) return NULL;
  490.    caps_max = caps + len;
  491.    while (caps < caps_max)
  492.      {
  493.     if ((c0 == caps[0]) && (c1 == caps[1]))
  494.       {
  495.          return (char *) caps + 3;
  496.       }
  497.     caps += (int) caps[2];
  498.      }
  499.    return NULL;
  500. }
  501.  
  502.    
  503. static int tcap_getnum (char *cap, Terminfo_Type *t)
  504. {
  505.    cap = tcap_get_cap ((unsigned char *) cap, t->numbers, t->num_numbers);
  506.    if (cap == NULL) return -1;
  507.    return atoi (cap);
  508. }
  509.  
  510. static char *tcap_getstr (char *cap, Terminfo_Type *t)
  511. {
  512.    return tcap_get_cap ((unsigned char *) cap, (unsigned char *) t->string_table, t->string_table_size);
  513. }
  514.  
  515. static int tcap_extract_field (unsigned char *t0)
  516. {
  517.    register unsigned char ch, *t = t0;
  518.    while (((ch = *t) != 0) && (ch != ':')) t++;
  519.    if (ch == ':') return (int) (t - t0);
  520.    return -1;
  521. }
  522.  
  523. int SLtt_try_termcap = 1;
  524. static int tcap_getent (char *term, Terminfo_Type *ti)
  525. {
  526.    unsigned char *termcap, ch;
  527.    unsigned char *buf, *b;
  528.    unsigned char *t;
  529.    int len;
  530.  
  531.    if (!SLtt_try_termcap == 0) return -1;
  532.    
  533.    termcap = (unsigned char *) getenv ("TERMCAP");
  534.    if ((termcap == NULL) || (*termcap == '/')) return -1;
  535.    
  536.    /* We have a termcap so lets use it provided it does not have a reference 
  537.     * to another terminal via tc=.  In that case, user terminfo.  The alternative
  538.     * would be to parse the termcap file which I do not want to do right now.
  539.     * Besides, this is a terminfo based system and if the termcap were parsed
  540.     * terminfo would almost never get a chance to run.  In addition, the tc=
  541.     * thing should not occur if tset is used to set the termcap entry.
  542.     */
  543.    t = termcap;
  544.    while ((len = tcap_extract_field (t)) != -1)
  545.      {
  546.     if ((len > 3) && (t[0] == 't') && (t[1] == 'c') && (t[2] == '='))
  547.       return -1;
  548.     t += (len + 1);
  549.      }
  550.    
  551.    /* malloc some extra space just in case it is needed. */
  552.    len = strlen ((char *) termcap) + 256;
  553.    if (NULL == (buf = (unsigned char *) SLMALLOC (len))) return -1;
  554.  
  555.    b = buf;
  556.    
  557.    /* The beginning of the termcap entry contains the names of the entry.
  558.     * It is terminated by a colon. 
  559.     */
  560.    
  561.    ti->terminal_names = (char *) b;
  562.    t = termcap;
  563.    len = tcap_extract_field (t);
  564.    if (len < 0)
  565.      {
  566.     SLFREE (buf);
  567.     return -1;
  568.      }
  569.    strncpy ((char *) b, (char *) t, len);
  570.    b[len] = 0;
  571.    b += len + 1;
  572.    ti->name_section_size = len;
  573.    
  574.    
  575.    /* Now, we are really at the start of the termcap entries.  Point the 
  576.     * termcap variable here since we want to refer to this a number of times.
  577.     */
  578.    termcap = t + (len + 1);
  579.    
  580.    
  581.    /* Process strings first. */
  582.    ti->string_table = (char *) b;
  583.    t = termcap;
  584.    while (-1 != (len = tcap_extract_field (t)))
  585.      {
  586.     unsigned char *b1;
  587.     unsigned char *tmax;
  588.     
  589.     /* We are looking for: XX=something */
  590.     if ((len < 4) || (t[2] != '=') || (*t == '.'))
  591.       {
  592.          t += len + 1;
  593.          continue;
  594.       }
  595.     tmax = t + len;
  596.     b1 = b;
  597.     
  598.     while (t < tmax)
  599.       {
  600.          ch = *t++;
  601.          if ((ch == '\\') && (t < tmax))
  602.            {
  603.           t = (unsigned char *) SLexpand_escaped_char ((char *) t, (char *) &ch);
  604.            }
  605.          else if ((ch == '^') && (t < tmax))
  606.            {
  607.           ch = *t++;
  608.           if (ch == '?') ch = 127;
  609.           else ch = (ch | 0x20) - ('a' - 1);
  610.            }
  611.          *b++ = ch;
  612.       }
  613.     /* Null terminate it. */
  614.     *b++ = 0;
  615.     len = (int) (b - b1);
  616.     b1[2] = (unsigned char) len;    /* replace the = by the length */
  617.     /* skip colon to next field. */
  618.     t++;
  619.      }   
  620.    ti->string_table_size = (int) (b - (unsigned char *) ti->string_table);
  621.  
  622.    /* Now process the numbers. */
  623.  
  624.    t = termcap;
  625.    ti->numbers = b;
  626.    while (-1 != (len = tcap_extract_field (t)))
  627.      {
  628.     unsigned char *b1;
  629.     unsigned char *tmax;
  630.     
  631.     /* We are looking for: XX#NUMBER */
  632.     if ((len < 4) || (t[2] != '#') || (*t == '.'))
  633.       {
  634.          t += len + 1;
  635.          continue;
  636.       }
  637.     tmax = t + len;
  638.     b1 = b;
  639.     
  640.     while (t < tmax)
  641.       {
  642.          *b++ = *t++;
  643.       }
  644.     /* Null terminate it. */
  645.     *b++ = 0;
  646.     len = (int) (b - b1);
  647.     b1[2] = (unsigned char) len;    /* replace the # by the length */
  648.     t++;
  649.      }   
  650.    ti->num_numbers = (int) (b - ti->numbers);
  651.    
  652.    /* Now process the flags. */
  653.    t = termcap;
  654.    ti->boolean_flags = b;
  655.    while (-1 != (len = tcap_extract_field (t)))
  656.      {
  657.     /* We are looking for: XX#NUMBER */
  658.     if ((len != 2) || (*t == '.') || (*t <= ' ')) 
  659.       {
  660.          t += len + 1;
  661.          continue;
  662.       }
  663.     b[0] = t[0];
  664.     b[1] = t[1];
  665.     t += 3;
  666.     b += 2;
  667.      }   
  668.    ti->boolean_section_size = (int) (b - ti->boolean_flags);
  669.    ti->flags = SLTERMCAP;
  670.    return 0;
  671. }
  672.  
  673. #else /* USE_SETUPTERM */
  674.  
  675. /* Ching Hui fixes so that it will work on AIX and OSF/1 */
  676. #include <curses.h>
  677. #include <term.h>
  678.  
  679. int SLtt_try_termcap = 1;
  680.  
  681. char *SLtt_tigetent (char *term)
  682. {
  683.     int rc;
  684.  
  685.     setupterm(term, 1, &rc);
  686.     if (rc != 1)
  687.     return NULL;
  688.     return (char *)cur_term;
  689. }
  690.  
  691. #define MATCH_CHAR(c, variable) \
  692.     do { \
  693.      if (*(cap + 1) == c) \
  694.          return variable; \
  695.      } while (0)
  696.  
  697. char *SLtt_tigetstr (char *cap, char **pp)
  698. {
  699.     if ((pp == NULL) || ((cur_term = (struct term *) *pp) == NULL))
  700.     return NULL;
  701.  
  702.     switch(*cap) {
  703.     case '@':
  704.     MATCH_CHAR('7', key_end);
  705.     break;
  706.     case 'A':
  707.     MATCH_CHAR('A', parm_insert_line);
  708.     break;
  709.     case 'D':
  710.     MATCH_CHAR('L', parm_delete_line);
  711.     break;
  712.     case 'R':
  713.     MATCH_CHAR('I', parm_right_cursor);
  714.     break;
  715.     case 'a':
  716. #ifdef  acs_chars
  717.     MATCH_CHAR('c', acs_chars);
  718. #elif defined (box_chars_1)
  719.     MATCH_CHAR('c', box_chars_1); /* AIX hack */
  720. #else
  721.     MATCH_CHAR('c', NULL);
  722. #endif
  723.     MATCH_CHAR('e', exit_alt_charset_mode);
  724.     MATCH_CHAR('s', enter_alt_charset_mode);
  725.     break;
  726.     case 'c':
  727.     MATCH_CHAR('e', clr_eol);
  728.     MATCH_CHAR('l', clear_screen);
  729.     MATCH_CHAR('m', cursor_address);
  730.     MATCH_CHAR('s', change_scroll_region);
  731.     break;
  732.     case 'd':
  733.     MATCH_CHAR('c', delete_character);
  734.     break;
  735.     case 'e':
  736.     MATCH_CHAR('i', exit_insert_mode);
  737. #ifdef ena_acs
  738.     MATCH_CHAR('A', ena_acs); /* aix hack */
  739. #else
  740.     MATCH_CHAR('A', NULL);
  741. #endif
  742.     break;
  743.     case 'i':
  744.     MATCH_CHAR('m', enter_insert_mode);
  745.     break;
  746.     case 'k':
  747.     MATCH_CHAR('0', key_f0);
  748.     MATCH_CHAR('1', key_f1);
  749.     MATCH_CHAR('1', key_f1);
  750.     MATCH_CHAR('2', key_f2);
  751.     MATCH_CHAR('3', key_f3);
  752.     MATCH_CHAR('4', key_f4);
  753.     MATCH_CHAR('5', key_f5);
  754.     MATCH_CHAR('6', key_f6);
  755.     MATCH_CHAR('7', key_f7);
  756.     MATCH_CHAR('8', key_f8);
  757.     MATCH_CHAR('9', key_f9);
  758.     MATCH_CHAR('A', key_il);
  759.     MATCH_CHAR('C', key_clear);
  760.     MATCH_CHAR('D', key_dc);
  761.     MATCH_CHAR('E', key_eol);
  762.     MATCH_CHAR('F', key_sf);
  763.     MATCH_CHAR('H', key_ll);
  764.     MATCH_CHAR('I', key_ic);
  765.     MATCH_CHAR('L', key_dl);
  766.     MATCH_CHAR('M', key_eic);
  767.     MATCH_CHAR('N', key_npage);
  768.     MATCH_CHAR('P', key_ppage);
  769.     MATCH_CHAR('R', key_sr);
  770.     MATCH_CHAR('S', key_eos);
  771.     MATCH_CHAR('T', key_stab);
  772.     MATCH_CHAR('a', key_catab);
  773.     MATCH_CHAR(';', key_f10);
  774.     MATCH_CHAR('b', key_backspace);
  775.     MATCH_CHAR('d', key_down);
  776.     MATCH_CHAR('e', keypad_local);
  777.     MATCH_CHAR('h', key_home);
  778.     MATCH_CHAR('l', key_left);
  779.     MATCH_CHAR('r', key_right);
  780.     MATCH_CHAR('s', keypad_xmit);
  781.     MATCH_CHAR('t', key_ctab);
  782.     MATCH_CHAR('u', key_up);
  783.     break;
  784.     case 'm':
  785.     MATCH_CHAR('b', enter_blink_mode);
  786.     MATCH_CHAR('d', enter_bold_mode);
  787.     MATCH_CHAR('e', exit_attribute_mode);
  788.     MATCH_CHAR('r', enter_reverse_mode);
  789.     break;
  790.     case 's':
  791.     MATCH_CHAR('e', exit_standout_mode);
  792.     MATCH_CHAR('o', enter_standout_mode);
  793.     MATCH_CHAR('r', scroll_reverse);
  794.     break;
  795.     case 't':
  796.     MATCH_CHAR('e', exit_ca_mode);
  797.     MATCH_CHAR('i', enter_ca_mode);
  798.     break;
  799.     case 'u':
  800.     MATCH_CHAR('p', cursor_up);
  801.     MATCH_CHAR('s', enter_underline_mode);
  802.     break;
  803.     case 'v':
  804.     MATCH_CHAR('b', flash_screen);
  805.     MATCH_CHAR('i', cursor_invisible);
  806.     MATCH_CHAR('s', cursor_visible);
  807.     break;
  808.     case 'F':
  809.     MATCH_CHAR('1', key_f11);
  810.     MATCH_CHAR('2', key_f12);
  811.     MATCH_CHAR('3', key_f13);
  812.     MATCH_CHAR('4', key_f14);
  813.     MATCH_CHAR('5', key_f15);
  814.     MATCH_CHAR('6', key_f16);
  815.     MATCH_CHAR('7', key_f17);
  816.     MATCH_CHAR('8', key_f18);
  817.     MATCH_CHAR('9', key_f19);
  818.     MATCH_CHAR('A', key_f20);
  819.     break;
  820. #ifdef orig_pair
  821.     case 'o':
  822.     MATCH_CHAR('p', orig_pair);
  823.     break;
  824. #endif
  825.     }
  826.     return NULL;
  827. }
  828.  
  829. int SLtt_tigetnum (char *cap, char **pp)
  830. {
  831.     if ((pp == NULL) || ((cur_term = (struct term *) *pp) == NULL))
  832.     return NULL;
  833.     switch(*cap) {
  834.     case 'c':
  835.     MATCH_CHAR('o', columns);
  836.     break;
  837.     case 'l':
  838.     MATCH_CHAR('i', lines);
  839.     break;
  840.     }
  841.     return -1;
  842. }
  843.  
  844. int SLtt_tigetflag (char *cap, char **pp)
  845. {
  846.     if ((pp == NULL) || ((cur_term = (struct term *) *pp) == NULL))
  847.     return NULL;
  848.     switch(*cap) {
  849.     case 'a':
  850.     MATCH_CHAR('m', auto_right_margin);
  851.     break;
  852.     case 'm':
  853.     MATCH_CHAR('s', move_standout_mode);
  854.     break;
  855.     case 'x':
  856.     MATCH_CHAR('s', ceol_standout_glitch);
  857.     break;
  858.     case 's':
  859.     MATCH_CHAR('g', magic_cookie_glitch);
  860.     break;
  861.     }
  862.     return -1;
  863. }
  864.  
  865. #endif /* !USE_SETUPTERM */
  866.